package com.base.cn.platform.os.service.classes;

import com.base.cn.platform.os.common.classes.ClassesStatisticsEnum;
import com.base.cn.platform.os.common.mybatis.BaseBiz;
import com.base.cn.platform.os.common.mybatis.Pagination;
import com.base.cn.platform.os.common.service.CommonSetCreateUserDataService;
import com.base.cn.platform.os.common.service.CommonSetSubjectDataService;
import com.base.cn.platform.os.common.utils.DataUtil;
import com.base.cn.platform.os.common.utils.ObjectUtils;
import com.base.cn.platform.os.common.utils.StringUtils;
import com.base.cn.platform.os.common.utils.result.ResultUtil;
import com.base.cn.platform.os.dao.classes.ClassesDao;
import com.base.cn.platform.os.entity.classes.Classes;
import com.base.cn.platform.os.entity.classes.member.ClassesMember;
import com.base.cn.platform.os.entity.course.cou.Course;
import com.base.cn.platform.os.entity.course.cou.CourseCondition;
import com.base.cn.platform.os.service.classes.member.ClassesMemberBiz;
import com.base.cn.platform.os.service.classes.topic.ClassesTopicBiz;
import com.base.cn.platform.os.service.course.cou.CourseBiz;
import com.base.cn.platform.os.service.manage.subject.SubjectService;
import com.base.cn.platform.os.service.manage.sysUser.SysUserService;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.stream.Collectors.joining;

/**
 * 班级
 *
 * @author SK
 * @since 2018-05-08
 */
@Service
public class ClassesBiz extends BaseBiz<Classes, ClassesDao> {

    @Autowired
    private ClassesMemberBiz classesMemberBiz;
    @Autowired
    private CommonSetCreateUserDataService<Classes> commonSetCreateUserDataService;
    @Autowired
    private CommonSetSubjectDataService<Classes> commonSetSubjectDataService;
    @Autowired
    private CourseBiz courseBiz;
    @Autowired
    private SubjectService subjectService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private ClassesTopicBiz classesTopicBiz;
    @Autowired
    private  ClassesDao classesDao;
    /**
     * 根据id查询班级
     *
     * @param id         班级id
     * @param setSubject 设置专业
     * @param setCreator 设置创建人
     * @param setCourse  设置课程
     * @param setMember  设置成员
     * @param order      排序 1.班主任->普通学员
     * @param identity   1.普通学员 2.班级管理员 3.班主任
     * @return 班级
     */
    public Classes findClassesById(BigDecimal id, boolean setSubject, boolean setCreator,
                                   boolean setCourse, boolean setMember, Integer order, int... identity) {
        Classes classes = findById(id);
        commonSetCreateUserDataService.setSysUserData(sysUserService, classes, setCreator);
        commonSetSubjectDataService.setSubjectData(subjectService, classes, setSubject);
        this.setClassesCourse(Collections.singletonList(classes), setCourse);
        this.setClassesMember(Collections.singletonList(classes), setMember, order, identity);
        return classes;
    }

    /**
     * 查询班级列表
     *
     * @param classes    班级查询条件
     * @param setSubject 设置专业
     * @param setCreator 设置创建人
     * @param setCourse  设置课程
     * @param setMember  设置成员
     * @param identity   1.普通学员 2.班级管理员 3.班主任
     * @return 班级列表
     */
    public List<Classes> findClassesList(Classes classes, boolean setSubject, boolean setCreator,
                                             boolean setCourse, boolean setMember, int... identity) {
        String where = this.where(classes);
        List<Classes> classesList = find(where, null, null);
        commonSetCreateUserDataService.setSysUserData(sysUserService, classesList, setCreator);
        commonSetSubjectDataService.setSubjectData(subjectService, classesList, setSubject);
        this.setClassesCourse(classesList, setCourse);
        this.setClassesMember(classesList, setMember, 0, identity);
        return classesList;
    }

    /**
     * 查询班级列表
     *
     * @param classes    班级查询条件
     * @param pagination 分页
     * @param setSubject 设置专业
     * @param setCreator 设置创建人
     * @param setCourse  设置课程
     * @param setMember  设置成员
     * @param identity   1.普通学员 2.班级管理员 3.班主任
     * @return 班级列表
     */
    public PageInfo<Classes> findClassesListPage(Classes classes, Pagination pagination, boolean setSubject,
                                                 boolean setCreator, boolean setCourse, boolean setMember,
                                                 int... identity) {
        String where = this.where(classes);
        PageInfo<Classes> pageInfo = findPage(where, pagination, null);
        commonSetCreateUserDataService.setSysUserData(sysUserService, pageInfo.getList(), setCreator);
        commonSetSubjectDataService.setSubjectData(subjectService, pageInfo.getList(), setSubject);
        this.setClassesCourse(pageInfo.getList(), setCourse);
        this.setClassesMember(pageInfo.getList(), setMember, 0, identity);
        this.getTopicNotHideNumber(pageInfo.getList());
        return pageInfo;
    }

    /**
     * 获取班级不隐藏的话题数量
     * @param list
     */
    private void  getTopicNotHideNumber(List<Classes> list){

        if(list!=null && !list.isEmpty()){
            int size =list.size();
            for(int i= 0;i<size;i++){
                //拼接sql 获取班级id status =1 不隐藏的话题
                String where = "classesId = "+list.get(i).getId()+" and status = 1";
                //查询不隐藏的话题数
                BigDecimal count = classesTopicBiz.count(where);
                list.get(i).setTopicCount(count.intValue());
            }

        }
    }

    /**
     * 保存班级
     *
     * @param classes 班级
     */
    @Transactional(rollbackFor =  IllegalArgumentException.class)
    public Classes saveClasses(Classes classes) {
        if (DataUtil.idIsNotNull(classes.getId())) {
            Classes database = findById(classes.getId());
            database.setName(classes.getName());
            database.setSummary(classes.getSummary());
            database.setSubjectIds(classes.getSubjectIds());
            database.setImageJson(classes.getImageJson());
            database.setClassesType(classes.getClassesType());
            database.setCourseId(classes.getCourseId());
            database.setFull(classes.getFull());
            this.updateById(database, null);
            classes = database;
        } else {
            String headmasterIds = StringUtils.subHeadTailString(classes.getHeadmasterIds(),",");
            classes.setHeadmasterIds(null);
            this.save(classes);
            if(StringUtils.isNotEmpty(headmasterIds)){
                BigDecimal classesId = classes.getId();
                BigDecimal courseId = classes.getCourseId();
                List<ClassesMember> memberList = new ArrayList<>();
                Stream.of(headmasterIds.split(",")).forEach((v) -> {
                    BigDecimal memberId = new BigDecimal(v);
                    ClassesMember classesMember = new ClassesMember();
                    classesMember.setMemberId(memberId);
                    classesMember.setClassesId(classesId);
                    classesMember.setCourseId(courseId);
                    classesMember.setIdentity(3);
                    classesMember.setStatus(1);
                    memberList.add(classesMember);
                });
                classesMemberBiz.batchSave(memberList);
            }
        }
        return classes;
    }

    /**
     * 更新班级状态
     *
     * @param ids    班级id
     * @param status 班级状态 1.正常 2.停班
     */
    public void updateClassesStatus(String ids, int status) {
        String where = " id in (" + ids + ")";
        Classes classes = new Classes();
        classes.setStatus(status);
        updateByWhereSql(classes, where);
    }

    public List<Map> getCourseRelevanceClasses(BigDecimal courseId){
      List<String>  containColumns = new ArrayList<>();
        containColumns.add("id");
        containColumns.add("name");
        containColumns.add("topicCount");
        containColumns.add("imageJson");
        StringBuffer  sql = new StringBuffer (" courseId = ");
        sql.append(courseId);
        sql.append(" ORDER  BY studentCount desc,topicCount desc LIMIT 0,8");
        List<Classes> classess = this.find(sql.toString(), null, containColumns);
        ArrayList<Map> objects = new ArrayList<>();
        for (Classes classes:classess){
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("id",classes.getId());
            hashMap.put("name",classes.getName());
            hashMap.put("topicCount",classes.getTopicCount());
            hashMap.put("imageMap",classes.getImageMap());
            objects.add(hashMap);
        }
        return objects;
    }

    /**
     * 更新班级统计
     *
     * @param statisticsMap 更新数据 key:班级id value:更新值
     * @param statistics    更新的统计类型
     */
    public void updateClassesStatistics(Map<String, Integer> statisticsMap, ClassesStatisticsEnum statistics) {
        if (ObjectUtils.isNotEmpty(statisticsMap)) {
            String ids = DataUtil.joining(statisticsMap.keySet(), Function.identity());
            Map<BigDecimal, Classes> classesMap = findClassesByIds(ids, false, false);
            switch (statistics) {
                case TOPIC_COUNT:
                    classesMap.forEach((k, v) -> {
                        int topicCount = v.getTopicCount() + statisticsMap.get(k.toString());
                        v.setTopicCount(topicCount);
                    });
                    break;
                case TOTAL_LEARN_TIME:
                    classesMap.forEach((k, v) -> {
                        long totalLearnTime = v.getTotalLearnTime() + statisticsMap.get(k.toString());
                        v.setTotalLearnTime(totalLearnTime);
                    });
                    break;
                default:
                    return;
            }
            List<Classes> update = new LinkedList<>(classesMap.values());
            updateBatch(update);
        }
    }

    /**
     * 根据id查询班级
     *
     * @param ids        班级id
     * @param setSubject 设置专业
     * @param setCreator 设置创建人
     * @return 班级 key:班级id value:班级
     */
    public Map<BigDecimal, Classes> findClassesByIds(String ids, boolean setSubject, boolean setCreator) {
        String where = " id in (" + ids + ")";
        List<Classes> classesList = find(where, null, null);
        commonSetSubjectDataService.setSubjectData(subjectService, classesList, setSubject);
        commonSetCreateUserDataService.setSysUserData(sysUserService, classesList, setCreator);
        return DataUtil.toMap(classesList, Classes::getId);
    }

    /**
     * 更新班级学员数
     *
     * @param refresh  更新数据 key:班级id value:增减人数
     * @param identity 1.普通学员 2.班级管理员 3.班主任
     * @return 操作结果
     */
    public Map<String, Object> refreshAndUpdateClasses(Map<BigDecimal, Long> refresh, int identity) {
        if (identity != 3 && ObjectUtils.isNotEmpty(refresh)) {
            String classesIds = DataUtil.joining(refresh.keySet(), Function.identity());
            Map<BigDecimal, Classes> classesMap = findClassesByIds(classesIds, false, false);
            List<Classes> classesList = new LinkedList<>(classesMap.values());
            // 计算班级人数
            classesList.forEach((v) -> {
                v.left();
                int studentCount = this.calculateStudentCount(v.getStudentCount(), refresh.get(v.getId()));
                v.setStudentCount(studentCount);
            });
            Optional<Classes> any = classesList.stream()
                    .filter(Classes::isOverflow)
                    .findAny();
            if (any.isPresent()) {
                if(any.get().getLeft() == 0){
                    return ResultUtil.ERROR("满班班级，无法再加入学员");
                }else {
                    return ResultUtil.ERROR("该班最多还可添加（" + any.get().getLeft() + "名）成员");
                }
            } else {
                updateBatch(classesList);
                return null;
            }
        }
        return null;
    }

    /**
     * 获取班级用户Ids
     * @param classIds
     * @return
     */
    public Map<BigDecimal,String> getUserIdsByClassIds(String classIds){
        if(StringUtils.isNotEmpty(classIds)){
            classIds=classIds.replaceAll(",,",",");
            classIds=StringUtils.subHeadTailString(classIds,",");
            List<ClassesMember> classUsers =classesMemberBiz.find(" classesId in ("+classIds+") and status=1 and  identity != 3",null,null);
            Map<BigDecimal,String>  classUserMap =classUsers.stream()
                    .collect(Collectors.groupingBy(ClassesMember::getClassesId, Collectors.mapping((v) -> v.getMemberId().toString(),
                            Collectors.collectingAndThen(Collectors.toList(), (v) -> v.stream().distinct().collect(joining(","))))));
            return classUserMap;
        }
        return null;
    }


    /**
     * 计算班级学员数
     *
     * @param studentCount 学员数
     * @param add          增减数
     * @return 学员数
     */
    private int calculateStudentCount(int studentCount, long add) {
        studentCount += add;
        return studentCount < 0 ? 0 : studentCount;
    }

    /**
     * 设置班级课程
     *
     * @param classesList 班级
     * @param setCourse   设置课程
     */
    private void setClassesCourse(List<Classes> classesList, boolean setCourse) {
        if (setCourse && ObjectUtils.isNotEmpty(classesList)) {
            String courseIds = DataUtil.joining(classesList, Classes::getCourseId);
            if (StringUtils.isNotEmpty(courseIds)){
                CourseCondition condition = new CourseCondition();
                condition.setIds(courseIds);
                condition.setOnLimit(true);
                List<Course> courseList = courseBiz.findCourseList(condition, false, false, false);
                Map<BigDecimal, Course> courseMap = DataUtil.toMap(courseList, Course::getId);
                classesList.forEach((v) -> {
                    if (DataUtil.idIsNotNull(v.getCourseId())) {
                        v.setCourse(courseMap.get(v.getCourseId()));
                    }
                });
            }
        }
    }

    /**
     * 设置班级成员
     *
     * @param classesList 班级
     * @param identity    1.普通学员 2.班长 3.班主任
     */
    private void setClassesMember(List<Classes> classesList, boolean setMember, Integer order, int... identity) {
        if (setMember && ObjectUtils.isNotEmpty(classesList)) {
            String classesIds = DataUtil.joining(classesList, Classes::getId);
            Map<BigDecimal, List<ClassesMember>> classesMemberMap = classesMemberBiz.findClassesMemberByClassesIds(classesIds, setMember, order, identity);
            classesList.forEach((v) -> v.setMemberList(classesMemberMap.get(v.getId())));
        }
    }

    /**
     * 拼接where子句
     *
     * @param classes 班级
     * @return where子句
     */
    private String where(Classes classes) {
        String where = " 1 = 1 ";
        if (StringUtils.isNotEmpty(classes.getName())) {
            where += " and name like '%" + classes.getName() + "%'";
        }
        if (StringUtils.isNotEmpty(classes.getSubjectIds())) {
            where += StringUtils.getSubjectSql("subjectIds", classes.getSubjectIds());
        }
        if (DataUtil.isPositive(classes.getStatus())) {
            where += " and status = " + classes.getStatus();
        }
        if (DataUtil.isPositive(classes.getClassesType())) {
            where += " and classesType = " + classes.getClassesType();
        }
        if (DataUtil.isPositive(classes.getFull())) {
            where += " and full = " + classes.getFull();
        }
        if (StringUtils.isNotEmpty(classes.getCourseIds())) {
            String courseIds = StringUtils.subHeadTailString(classes.getCourseIds(),",");
            where += " and courseId in (" +courseIds + ")";
        }
        if (StringUtils.isNotEmpty(classes.getIds())) {
            String ids = StringUtils.subHeadTailString(classes.getIds(),",");
            where += " and id in (" +ids + ")";
        }
        where += " order by createTime desc";
        return where;
    }

    public BigDecimal getClassCount(Classes classes) {
        String whereSql = this.where(classes);
        BigDecimal count = this.count(whereSql);
        if(!DataUtil.idIsNotNull(count)){
            count = BigDecimal.ZERO;
        }
        return count;
    }
}
